

#ifndef CPIE_QUEUE_DISC_H
#define CPIE_QUEUE_DISC_H

#include "ns3/queue-disc.h"
#include "ns3/nstime.h"
#include "ns3/boolean.h"
#include "ns3/data-rate.h"
#include "ns3/timer.h"
#include "ns3/event-id.h"
#include "ns3/random-variable-stream.h"
#include "ns3/ipv4-queue-disc-item.h"

#define BURST_RESET_TIMEOUT 1.5
// Edit by PassLink.cn


// class PieQueueDiscTestCase; // Forward declaration for unit test
namespace ns3
{

  class TraceContainer;
  class UniformRandomVariable;

  /**
   * \ingroup traffic-control
   *
   * \brief Implements PIE Active Queue Management discipline 此类实现主要的PIE算法
   */
  class cPieQueueDisc : public QueueDisc
  {
  public:


    /**
     * \brief Get the type ID.
     * \return the object TypeId
     */
    static TypeId GetTypeId(void);

    /**
     * \brief cPieQueueDisc Constructor
     */
    cPieQueueDisc();

    /**
     * \brief cPieQueueDisc Destructor
     */
    virtual ~cPieQueueDisc();

    /**
     * \brief Burst types
     */
    enum BurstStateT
    {
      NO_BURST,
      IN_BURST,
      IN_BURST_PROTECTING,
    };

    /**
     * \brief Get queue delay.
     *
     * \returns The current queue delay.
     */
    Time GetQueueDelay(void);
    /**
     * Assign a fixed random variable stream number to the random variables
     * used by this model.  Return the number of streams (possibly zero) that
     * have been assigned.
     *
     * \param stream first stream index to use
     * \return the number of stream indices assigned by this model
     */
    int64_t AssignStreams(int64_t stream);

    // Reasons for dropping packets
    static constexpr const char *UNFORCED_DROP = "Unforced drop";                           //!< Early probability drops: proactive
    static constexpr const char *FORCED_DROP = "Forced drop";                               //!< Drops due to queue limit: reactive
    static constexpr const char *UNFORCED_MARK = "Unforced mark";                           //!< Early probability marks: proactive
    static constexpr const char *CE_THRESHOLD_EXCEEDED_MARK = "CE threshold exceeded mark"; //!< Early probability marks: proactive


  protected:
    /**
     * \brief Dispose of the object
     */
    virtual void DoDispose(void);


  private:
    // friend class ::PieQueueDiscTestCase; // Test code
    // 此例程检查队列是否已满，如果已满，则丢弃数据包并记录由于队列溢出而导致的丢弃次数。
    //  如果队列未满，则如果设置了ActiveThreshold，则检查队列延迟是否高于ActiveThreshold
    //  如果是，则此例程调用“PieQueueDisc:：DropEarly（）”，并根据返回的值
    //  将传入数据包排入队列或丢弃。
    virtual bool DoEnqueue(Ptr<QueueDiscItem> item);
    /**
     * 此例程使用时间戳（默认情况下）计算队列延迟，或者，在启用`UseDequeRateEstimator`属性的情况下，
     * 计算平均出发率以估计队列延迟。更新“PieQueueDisc:：CalculateP（）”中的丢弃概率所需的队列延迟估计。
     * 从ns-3.32版本开始，计算队列延迟的默认方法已更改为使用时间戳。
     *
     */
    virtual Ptr<QueueDiscItem> DoDequeue(void);
    virtual bool CheckConfig(void);

    /**
     * \brief Initialize the queue parameters.
     */
    virtual void InitializeParams(void);

    /**
     * \brief Check if a packet needs to be dropped due to probability drop
     * \param item queue item
     * \param qSize queue size
     * \returns 0 for no drop, 1 for drop
     * 通过调用此例程来决定将数据包排队或丢弃，该例程返回布尔值；false表示入队，true表示放弃。
     */
    bool DropEarly(Ptr<QueueDiscItem> item, uint32_t qSize);

    /**
     * Periodically update the drop probability based on the delay samples:
     * not only the current delay sample but also the trend where the delay
     * is going, up or down
     * 此例程以`m_tUpdate`的定期间隔调用，并更新``PieCQueueDisc：：DropEarly（）所需的丢弃概率
     */
    void CalculateP();

    static const uint64_t DQCOUNT_INVALID = std::numeric_limits<uint64_t>::max(); //!< Invalid dqCount value

    // ** Variables supplied by user
    Time m_sUpdate;             //!< Start time of the update timer
    Time m_tUpdate;             //!< Time period after which CalculateP () is called
    Time m_qDelayRef;           //!< Desired queue delay
    uint32_t m_meanPktSize;     //!< Average packet size in bytes
    Time m_maxBurst;            //!< Maximum burst allowed before random early dropping kicks in
    double m_a;                 //!< Parameter to pie controller
    double m_b;                 //!< Parameter to pie controller
    uint32_t m_dqThreshold;     //!< Minimum queue size in bytes before dequeue rate is measured
    bool m_useDqRateEstimator;  //!< Enable/Disable usage of dequeue rate estimator for queue delay calculation
    bool m_isCapDropAdjustment; //!< Enable/Disable Cap Drop Adjustment feature mentioned in RFC 8033
    bool m_useEcn;              //!< Enable ECN Marking functionality
    bool m_useDerandomization;  //!< Enable Derandomization feature mentioned in RFC 8033
    double m_markEcnTh;         //!< ECN marking threshold (default 10% as suggested in RFC 8033)
    Time m_activeThreshold;     //!< Threshold for activating PIE (disabled by default)
    Time m_ceThreshold;         //!< Threshold above which to CE mark
    bool m_useL4s;              //!< True if L4S is used (ECT1 packets are marked at CE threshold)
    
    // ****************************添加代码************************************//
    // 计时器
    Time m_lastClearTime;
    // 清理时间阈值
    Time m_clearThreshold;
    // // 桶大小
    // uint32_t m_cuckooHashSize;
    // ****************************添加代码************************************//

    // ** Variables maintained by PIE
    double m_dropProb;               //!< 丢包概率 Variable used in calculation of drop probability
    Time m_qDelayOld;                //!< Old value of queue delay
    Time m_qDelay;                   //!< Current value of queue delay
    Time m_burstAllowance;           //!< Current max burst value in seconds that is allowed before random drops kick in
    uint32_t m_burstReset;           //!< Used to reset value of burst allowance
    BurstStateT m_burstState;        //!< Used to determine the current state of burst
    bool m_inMeasurement;            //!< Indicates whether we are in a measurement cycle
    double m_avgDqRate;              //!< Time averaged dequeue rate
    Time m_dqStart;                  //!< Start timestamp of current measurement cycle
    uint64_t m_dqCount;              //!< Number of bytes departed since current measurement cycle starts
    EventId m_rtrsEvent;             //!< Event used to decide the decision of interval of drop probability calculation
    Ptr<UniformRandomVariable> m_uv; //!< Rng stream
    double m_accuProb;               //!< Accumulated drop probability
    bool m_active;                   //!< Indicates whether PIE is in active state or not
  };

}; // namespace ns3

#endif
